<?php

  /**
   * @author Dany Mottier
   * @version 2.3.2
   */
  class File extends Base implements IFile {

    /** @var string The full path of the file. */
    private $path = "";

    /** @var string The name of the file. */
    private $filename = "";

    /** @var integer The size of the file. */
    private $size = 0;

    /** @var string The creation date of the file. */
    private $creation = "";

    /** @var string The last modification date of the file. */
    private $modification = "";

    /** @var string The last access time of the file. */
    private $access = "";

    /** @var string The content of the file. */
    private $content = "";

    /** @var resource The pointer in the file. */
    private $pointer = NULL;

    /**
     * Store the full path in private privateiable and determine all properties for
     * further use.<br />
     *
     * @param string $path The full path to the file.
     *
     * @link http://be2.php.net/manual/en/function.basename.php
     * @link http://be2.php.net/manual/en/function.filesize.php
     * @link http://be2.php.net/manual/en/function.date.php
     * @link http://be2.php.net/manual/en/function.filectime.php
     * @link http://be2.php.net/manual/en/function.filemtime.php
     * @link http://be2.php.net/manual/en/function.fileatime.php
     */
    public function __construct($path) {
      if (is_string($path)) {
        $this->path = $path;
        $this->filename = basename($path);

        if (file_exists($path)) {
          $this->size = filesize($path);
          $this->creation = date("d/m/Y H:i:s", filectime($path));
          $this->modification = date("d/m/Y H:i:s", filemtime($path));
          $this->access = date("d/m/Y H:i:s", fileatime($path));
        }
        else
          throw new IOException("File does not exists");
      }
      else
        throw new IOException("\$path parameter should be a string");
    }

    /**
     * Returns the full path of the file.<br />
     *
     * @return string The full path.
     */
    public function getPath() {
      return $this->path;
    }

    /**
     * Returns the name of the file.<br />
     *
     * @return string The filename.
     */
    public function getFileName() {
      return $this->filename;
    }
    
    /**
     * Returns the extension of the file.
     * @return string The file extension.
     */
    public function getExtension() {
      return substr($this->filename, strrpos($this->filename, "."));
    }

    /**
     * Returns the size of the file.<br />
     *
     * @return integer The size or FALSE in case of exception.<br /><br />
     * 
     * @exception EWARNING Raised on error.
     */
    public function getSize() {
      return $this->size;
    }

    /**
     * Returns the creation date and time of the file.<br />
     *
     * @return string The creation date and time.
     */
    public function getCreation() {
      return $this->creation;
    }

    /**
     * Returns the creation date of the file.<br />
     *
     * @return string The creation date.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.substr.php
     * @link http://be2.php.net/manual/en/function.strpos.php
     */
    public function getCreationDate() {
      return substr($this->creation, 0, strpos($this->creation, " "));
    }

    /**
     * Returns the creation time of the file.<br />
     *
     * @return string The creation time.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.substr.php
     * @link http://be2.php.net/manual/en/function.strpos.php
     * @link http://be2.php.net/manual/en/function.strlen.php
     */
    public function getCreationTime() {
      return substr($this->creation, strpos($this->creation, " "), strlen($this->creation) - strpos($this->creation, " "));
    }

    /**
     * Returns the last modification date and time of the file.<br />
     *
     * @return string The last modification date and time.
     */
    public function getModification() {
      return $this->modification;
    }

    /**
     * Returns the last modification date of the file.<br />
     *
     * @return string The last modification date.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.substr.php
     * @link http://be2.php.net/manual/en/function.strpos.php
     */
    public function getModificationDate() {
      return substr($this->modification, 0, strpos($this->modification, " "));
    }

    /**
     * Returns the last modification time of the file.<br />
     *
     * @return string The last modification time of the file.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.substr.php
     * @link http://be2.php.net/manual/en/function.strpos.php
     * @link http://be2.php.net/manual/en/function.strlen.php
     */
    public function getModificationTime() {
      return substr($this->modification, strpos($this->modification, " "), strlen($this->modification) - strpos($this->modification, " "));
    }

    /**
     * Returns the last acces date and time of the file.<br />
     *
     * @return string The last access date and time of the file.
     */
    public function getLastAccess() {
      return $this->access;
    }

    /**
     * Returns the last access date of the file.<br />
     *
     * @return string The last access date of the file.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.substr.php
     * @link http://be2.php.net/manual/en/function.strpos.php
     */
    public function getLastAccessDate() {
      return substr($this->access, 0, strpos($this->access, " "));
    }

    /**
     * Returns the last access time of the file.<br />
     *
     * @return string The last access time of the file.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.substr.php
     * @link http://be2.php.net/manual/en/function.strpos.php
     * @link http://be2.php.net/manual/en/function.strlen.php
     */
    public function getLastAccessTime() {
      return substr($this->access, strpos($this->access, " "), strlen($this->access) - strpos($this->access, " "));
    }

    /**
     * Abstract method to get the type of the file.<br />
     *
     * @param string $filename Path to the file.
     *
     * @return string Returns the type of the given file.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.empty.php
     * @link http://be2.php.net/manual/en/function.filetype.php
     */
    public function getType($filename = "") {
      if (is_string($filename))
        if (!empty($filename))
          return filetype($filename);
        else
          return filetype($this->path);
      else
        throw new IOException("\$filename parameter should be a string");
    }

    /**
     * Abstract method that tells whether the filename is a regular file.<br />
     *
     * @param string $filename Path to the file.
     *
     * @return boolean TRUE if the filename exists and is a regular file, FALSE otherwise.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.is-file.php
     */
    public function isFile($filename = "") {
      if (!empty($filename)) {
        if (is_string($filename)) {
          return is_file($filename);
        } else {
          throw new IllegalArgumentException("\$filename parameter should be a string");
        }
      } else {
        print $this->filename;
        return is_file($this->filename);
      }
    }

    /**
     * Define if the pointer is NULL or not.<br />
     *
     * @return boolean Returns FALSE if the pointer is not NULL.
     */
    public function isNull() {
      return is_null($this->pointer);
    }

    /**
     * Deletes a file.<br />
     * Deletes filename . Similar to the Unix C unlink() function.<br />
     *
     * @param string $filename Path to the file.
     *
     * @return IBoolean Returns TRUE on success or FALSE on failure.<br />
     *
     * @link http://be2.php.net/manual/en/function.empty.php
     * @link http://be2.php.net/manual/en/function.is-string.php
     * @link http://be2.php.net/manual/en/function.unlink.php
     */
    public function delete($filename = "") {
      if (!empty($filename))
        if (is_string($filename))
          return unlink($filename);
        else
          throw new IllegalArgumentException("\$filename parameter should be a string");
      else
        return unlink($this->filename);
    }

    /**
     * Tests for end-of-file on a file pointer.<br />
     *
     * @return IBoolean TRUE if the file pointer is at EOF or an error occurs; otherwise returns FALSE.<br /><br />
     *
     * @link http://be.php.net/manual/en/function.feof.php
     */
    public function endOfStream() {
      return feof($this->pointer);
    }

    /**
     * Checks whether a file or directory exists.<br />
     *
     * @param string $filename Path to the file or directory. On windows, use
     * //computername/share/filename or \\computername\share\filename to check
     * files on network shares.
     *
     * @return IBoolean TRUE if the file or directory specified by filename exists, FALSE
     * otherwise.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.empty.php
     * @link http://be2.php.net/manual/en/function.file-exists.php
     */
    public function exists($filename = "") {
      if (is_string($filename)) {
        if (!empty($filename))
          return file_exists($filename);
        else
          return file_exists($this->path);
      }
      else
        throw new IllegalArgumentException("\$filename parameter should be a string");
    }
    
    /**
     * Binary-safe file read.<br />
     * Reads up to length  bytes from the file pointer referenced by handle.<br />
     *
     * @param integer $length Up to length  number of bytes read.
     *
     * @return mixed The read string or FALSE in case of error.<br /><br />
     *
     * @link http://be.php.net/manual/en/function.fgets.php
     */
    public function readLine($length = 1024) {
      if (is_int($length))
        return fgets($this->pointer, $length);
      else
        throw new IllegalArgumentException("\$length parameter should be an integer");
    }

    /**
     * Reads the entire file.<br />
     *
     * @return mixed The read data or FALSE on failure.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.file-get-contents.php
     */
    public function readToEnd() {
      $this->content = file_get_contents($this->path);

      return $this->content;
    }

    /**
     * Rename the file with the new name.<br />
     * The old file could not be deleted but empty.<br />
     *
     * @param string $new_name
     *
     * @return boolean True on success
     */
    public function rename($new_name) {
      if (is_string($new_name)) {
        $success = @rename($this->path, $new_name);

        if ($success) {
          $this->path = $new_name;
          $this->filename = basename($new_name);
          $this->creation = date("d/m/Y H:i:s", @filectime($this->path));
          $this->modification = date("d/m/Y H:i:s", @filemtime($this->path));
          $this->access = date("d/m/Y H:i:s", @fileatime($this->path));

          return TRUE;
        }
        else
          throw new IOException("Can not rename file.");
      }
      else
        throw new IllegalArgumentException("\$new_name parameter should be a string");
    }

    /**
     * Opens file or URL.<br />
     * Binds a named resource to a stream.<br />
     *
     * @param string The mode parameter specifies the type of access you require to the
     * stream. It may be any of the following : 'r', 'r+', 'w', 'w+', 'a', 'a+',
     * 'x' and 'x+'. See <a href="http://be2.php.net/manual/en/function.fopen.php
     *
     * @link http://be2.php.net/manual/en/function.fopen.php">fopen()</a>
     */
    public function open($mode) {
      if (is_string($mode))
        $this->pointer = fopen($this->path, $mode);
      else
        throw new IllegalArgumentException("\$mode parameter should be a string");
    }

    /**
     * Binary-safe file write.<br />
     * Writes the contents of string to the file stream pointed to by handle.<br />
     *
     * @param string $content The string that is to be written.
     *
     * @return integer The number of bytes written, or FALSE on error.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.fwrite.php
     */
    public function writeLine($content) {
      if (is_string($content))
        return fwrite($this->pointer, $content . "\r\n");
      else
        throw new IllegalArgumentException("\$content parameter should be a string");
    }

    /**
     * Closes an open file pointer.<br />
     * The file pointed to by handle is closed.
     *
     * @return IBoolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.fclose.php
     */
    public function close() {
      return new Boolean(fclose($this->pointer));
    }

  }

?>
